using DataBase.Utils;
using GreenXi.Help.Plc;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;
using Util;
using static GreenXi.GlobalVariables;
using static GreenXi.Help.Curve.ClsJudge;

namespace GreenXi.Help
{
    public class MultiCard
    {
        public static MultiCardCS.MultiCardCS MultiCardCS_1 = new();

        public static int AlternateUnits = 5000;

        public static double testYaLi = 0;

        public static double testWeiYi = 0;

        //方向 true 正向 false反向
        public static bool Direction = true;



        /// <summary>
        /// 当前位置
        /// </summary>
        public static double NowPoint;

        public static bool isConnected = false;

        //！！！该系统控制的压机没有机械硬限位，没有自动回零，一定要设置好机械原点在61mm处，否则该系统就会导致出现问题！！！


        //返回值 意义 处理方法
        //0 执行成功
        //1 执行失败 检测命令执行条件是否满足
        //2 版本不支持该 API 如有需要，联系厂家
        //7 参数错误 检测参数是否合理
        //-1 通讯失败 接线是否牢靠，更换板卡
        //-6 打开控制器失败 是否输入正确串口名，是否调用 2 次 MC_Open
        //-7 运动控制器无响应 检测运动控制器是否连接，是否打开。更换板卡

        /// <summary>
        /// 打开板卡
        /// </summary>
        /// <returns>返回0是打开成功</returns>
        public static int Init()
        {
            return OpenCard();
        }
        

        /// <summary>
        /// 打开板卡
        /// </summary>
        /// <returns>返回0是打开成功</returns>
        public static int OpenCard()
        {
			Helpers.Logger.Instance.Warning($"打开板卡 OpenCard");
            int iRes = 0;
            PLC1 pLC = new();
            short CardNum = MyDbContext.GetSettingByDb<short>("CardNum1");
            var PCEthernetIP = MyDbContext.GetSettingByDb<string>("PCEthernetIP");
            var PCEthernetPort = MyDbContext.GetSettingByDb<ushort>("PCEthernetPort");
            var CardEthernetIP = MyDbContext.GetSettingByDb<string>("CardEthernetIP");
            var CardEthernetPort = MyDbContext.GetSettingByDb<ushort>("CardEthernetPort");
            var CompressorsNumber = int.Parse(MyDbContext.Instance.Settings.FirstOrDefault(x => x.Key == "CompressorsNumber").Value);

            //GA_Open的4个参数依次是卡号、PC端IP地址、PC端端口号、板卡端IP地址、板卡端端口号
            try
            {
              iRes = MultiCardCS_1.GA_Open(
            CardNum,
            PCEthernetIP,
            PCEthernetPort,
            CardEthernetIP,
            CardEthernetPort
            );
                if (iRes == 0)
                {
                    //使能+松抱闸
                    MultiCardCS_1.GA_AxisOn(CardNum);
                    MultiCardCS_1.GA_AxisOn(CardNum);

                    //使能轴（通常设置一次即可，不是每次必须）
                    LooseBrake(CardNum);
                    pLC.SetPLC("MES_Enable1", true);
                    ///设置超时时间
                    SetCommuTimer(1);
                    //运动控制卡减速度,每次都需要
                    SetStopDec(1);

                    if (CompressorsNumber == 2)
                    {
                        pLC.SetPLC("MES_Enable2", true);
                        //运动控制卡减速度,每次都需要
                        SetStopDec(2);
                    }
                }
                
                isConnected = true;
                GlobalVariables.IsMotionControlCard1Connected = true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("运动控制卡连接失败");
                Helpers.Logger.Instance.Error(ex,$"运动控制卡连接失败");
                GlobalVariables.IsMotionControlCard1Connected = false;
                if (GlobalVariables.CallPolice == 0)
                {
                    GlobalVariables.CallPolice = (int)GlobalVariables.CallPoliceStatus.运动控制卡断开连接;
                }
                
                iRes = -1;
            }
            return iRes;
        }

       

        public static void LooseBrake(short CardNum)
        {
            using MyDbContext myDbContext = new MyDbContext();
            MyDbContext.SetLog("松开抱闸");
			Helpers.Logger.Instance.Warning($"MultiCard 松开抱闸");
			int iRes = 0;
            short nBitIndex = 0;
            short nValue = 0;
            short nCardIndex = 0;

            iRes = MultiCardCS_1.GA_GetExtDoBit(nCardIndex, nBitIndex, ref nValue);

            iRes = MultiCardCS_1.GA_SetExtDoBit(nCardIndex, nBitIndex, 1);
        }

        public static void HoldingBrake()
        {
            using MyDbContext myDbContext = new MyDbContext();
            MyDbContext.SetLog("紧抱闸");
			Helpers.Logger.Instance.Warning($"MultiCard 紧抱闸");
			int iRes = 0;
            short nBitIndex = 0;
            short nValue = 0;

            short nCardIndex = 0;

            iRes = MultiCardCS_1.GA_GetExtDoBit(nCardIndex, nBitIndex, ref nValue);

            iRes = MultiCardCS_1.GA_SetExtDoBit(nCardIndex, nBitIndex, 0);
        }

        /// <summary>
        /// 绝对运动
        /// </summary>
        /// <param name="position">位移</param>
        /// <param name="speed">速度</param>
        /// <param name="AxisNum">压机号</param>
        public static void AbsoluteMotion(double position, double speed, short AxisNum)
        {
            double dPrfPos = 0;
            int lClock = 0;

            Helpers.Logger.Instance.Infomation($"开始AbsoluteMotion位移{position},速度{speed}");
            ///判断是否同步位移成功和是否报警
            if (!SetPrfPos(ModBus.GetPositionOld(AxisNum), AxisNum)|| CallPolice!=0)
            {
                return;
            }
           

            Helpers.Logger.Instance.Warning($"MultiCard AbsoluteMotion");
			if (speed > GlobalVariables.MaximumSpeed)
            {
                speed = GlobalVariables.MaximumSpeed;
            }

            if (!IsCheck(position, AxisNum))
            {
                return;
            }

            position = position * GlobalVariables.PulseConfiguration;
            if (!Direction)
            {
                position = -position;
            }

            int iRes = 0;
            short nAxisNum = AxisNum;
            MultiCardCS.MultiCardCS.TTrapPrm m_TrapPrm;

            //加速度，单位：脉冲/毫秒/毫秒
            m_TrapPrm.acc = GlobalVariables.Acceleration;
            //减速度，单位：脉冲/毫秒/毫秒
            m_TrapPrm.dec = GlobalVariables.Deceleration;
            //平滑时间(需要设置为0)
            m_TrapPrm.smoothTime = 0;
            //启动速度(需要设置为0)
            m_TrapPrm.velStart = 0;

            //使能轴（通常设置一次即可，不是每次必须）
            iRes = MultiCardCS_1.GA_AxisOn(nAxisNum);
            //设置为点位模式（通常设置一次即可，不是每次必须）
            iRes = MultiCardCS_1.GA_PrfTrap(nAxisNum);

            //设置点位运动参数
            iRes = MultiCardCS_1.GA_SetTrapPrm(nAxisNum, ref m_TrapPrm);
            //设置点位运动速度
            iRes = MultiCardCS_1.GA_SetVel(nAxisNum, speed / 2);

            //获取当前规划位置（脉冲位置）
            iRes = MultiCardCS_1.GA_GetPrfPos(nAxisNum, ref dPrfPos, 1, ref lClock);

            //设置目标位置
            iRes = MultiCardCS_1.GA_SetPos(nAxisNum, (int)position);
			Helpers.Logger.Instance.Warning($"MultiCard GA_SetPos  绝对运动 设置目标位置");
			short nValue = 0;

            if (MultiCardCS_1.GA_GetExtDoBit(AxisNum, 0, ref nValue) == 1)
            {
                LooseBrake(AxisNum);
            }

            //启动运动
            iRes = MultiCardCS_1.GA_Update(0X0001 << (nAxisNum - 1));
			Helpers.Logger.Instance.Warning($"MultiCard GA_Update 绝对运动 启动运动");

		}

	
        /// <summary>
        /// 获取位移处理过的数据
        /// </summary>
        /// <param name="nAxisNum"></param>
        /// <returns></returns>
		public static double GetPosition(short nAxisNum)
        {

            var pos = GetPositionOld(nAxisNum);
            if(pos != -9999)
            {
                return Math.Round(pos / GlobalVariables.PulseConfiguration, 2);
            }
            else
            {
                return pos;
            }
        }

        /// <summary>
        /// 获取位移原值
        /// </summary>
        /// <param name="nAxisNum"></param>
        /// <returns></returns>
        public static double GetPositionOld(short nAxisNum)
        {
            try
            {
                double dPrfPos = -9999;
                int lClock = 0;
                var iRes = MultiCardCS_1.GA_GetPrfPos(nAxisNum, ref dPrfPos, 1, ref lClock);

                //TimeSpan timeout = TimeSpan.FromMilliseconds(200);
                //var iRes = PressUtil.ExecuteWithTimeout(() => MultiCardCS_1.GA_GetPrfPos(nAxisNum, ref dPrfPos, 1, ref lClock), timeout);
                if (iRes == 0)
                {
                    return dPrfPos;
                }
                else
                {
                    Helpers.Logger.Instance.Warning($"压机{nAxisNum}GetPositionOld失败");
                    //报警
                    if (GlobalVariables.CallPolice == 0)
                    {
                        GlobalVariables.CallPolice = (int)GlobalVariables.CallPoliceStatus.运动控制卡断开连接;
                    }
                    return dPrfPos;
                }
            }
            catch(Exception e)
            {
                return -9999;
            }
            
           
        }


        //TODO 急停的速度运动要另写，急停的减速度快一点，普通的减速度慢一点，否则有声音
        /// <summary>
        /// 速度运动
        /// </summary>
        /// <param name="AxisNum"></param>
        public static void JogMotion(double speed, short nAxisNum)
        {
            int iRes = 0;
            if (speed > GlobalVariables.MaximumSpeed)
            {
                speed = GlobalVariables.MaximumSpeed;
            }
            MultiCardCS.MultiCardCS.TJogPrm m_JogPrm;

            //加速度，单位：脉冲/毫秒/毫秒
            m_JogPrm.dAcc = GlobalVariables.Acceleration;
            //减速度，单位：脉冲/毫秒/毫秒
            m_JogPrm.dDec = GlobalVariables.Deceleration;
            //平滑时间(需要设置为0)
            m_JogPrm.dSmooth = 0;

            //使能轴（通常设置一次即可，不是每次必须）
            iRes = MultiCardCS_1.GA_AxisOn(nAxisNum);

            //设置为速度模式（通常设置一次即可，不是每次必须）
            iRes = MultiCardCS_1.GA_PrfJog(nAxisNum);

            //设置运动参数
            iRes = MultiCardCS_1.GA_SetJogPrm(nAxisNum, ref m_JogPrm);

            //设置速度
            iRes = MultiCardCS_1.GA_SetVel(nAxisNum, speed / 2);

            //启动运动
            iRes = MultiCardCS_1.GA_Update(0X0001 << (nAxisNum - 1));
        }


        /// <summary>
        /// 设置减速度
        /// </summary>
        /// <param name="nAxisNum"></param>
        public static void SetStopDec(short nAxisNum)
        {
            var iRes = MultiCardCS_1.GA_SetStopDec(1,0.5,15); //设置轴  停止运动
        }
        /// <summary>
        /// 停止运动
        /// </summary>
        /// <param name="AxisNum">压机编号</param>
        public static void Stop(short AxisNum)
        {
            int iRes = 0;
            try
            {
				if (AxisNum == 1)
				{
					iRes += MultiCardCS_1.GA_Stop((0X0001 << (AxisNum - 1)), 0); //设置轴  停止运动
				}
				else if (AxisNum == 2 && GlobalVariables.CompressorsNumber == 2)
				{
					iRes += MultiCardCS_1.GA_Stop((0X0001 << (AxisNum - 1)), 0); //设置轴  停止运动
				}
			}
            catch (Exception ex)
            {
                MessageBox.Show("停止运动控制卡失败");
				Helpers.Logger.Instance.Error(ex,$"停止控制卡失败");
			}
            GlobalVariables.SetIsRunning(AxisNum, false);
        }
        /// <summary>
        /// 设置读取超时时间
        /// </summary>
        /// <param name="Time"></param>
        public static bool SetCommuTimer(int Time)
        {
            var iRes = MultiCardCS_1.GA_SetCommuTimer(Time);
            if (iRes == 0)
            {
                return true;
            }
            return false;
        }

        /// <summary>
        /// 获取轴状态
        /// 512是 运动停止
        /// </summary>
        /// <param name="AxisNum"></param>
        public static bool GetStr(short AxisNum)
        {
            int lSts = 0;
            int lClock = 0;
            var iRes=MultiCardCS_1.GA_GetSts(AxisNum, ref lSts, 1, ref lClock);
            if (iRes == 0)
            {
                if (lSts == 512|| lSts==2560)//512不是运动状态
                {
                    return true;
                }
                else
                {
                    return false;   
                }
              
            }
            else
            {
                Helpers.Logger.Instance.Warning($"压机{AxisNum}GetStr获取轴状态:{iRes}");
                if (GlobalVariables.CallPolice == 0)
                {
                    GlobalVariables.CallPolice = (int)GlobalVariables.CallPoliceStatus.运动控制卡断开连接;
                }
                return false;
            }

        }
        public static bool SetPrfPos(int position, short AxisNum)
        {
            if (position == -9999)
            {
                return false;
            }
            #region 判断轴状态
            //获取轴状态 如果轴在运动等待10毫秒再读一次
            bool StrStatus =false;
            for(int i = 0; i < 10; i++)
            {
                if (GetStr(AxisNum))
                {
                    StrStatus= true;
                    break;
                }
                Task.Delay(10);
            }
            if(!StrStatus)
            {
                return false;
            }
            #endregion

            int iRes = MultiCardCS_1.GA_SetPrfPos(AxisNum, position);
            if(iRes == 0)
            {
                return true;
            }
            else
            {
                Helpers.Logger.Instance.Warning($"压机{AxisNum}SetPrfPos位移position:{position}失败iRes:{iRes}");
                if (GlobalVariables.CallPolice == 0)
                {
                    GlobalVariables.CallPolice = (int)GlobalVariables.CallPoliceStatus.运动控制卡断开连接;
                }
                return false;
            }
        }

        /// <summary>
        /// 是否链接成功
        /// </summary>
        /// <param name="AxisNum"></param>
        /// <returns></returns>
        public static bool HeartBeat(short AxisNum)
        {
            double dPrfPos = 0;
            int lClock = 0;
            var iRes = MultiCardCS_1.GA_GetPrfPos(AxisNum, ref dPrfPos, 1, ref lClock);
            //0是连接成功,其他是连接失败
            if(iRes == 0){
                return true;
            }
            else
            {
                isConnected = false;
                if (GlobalVariables.CallPolice == 0)
                {
                    GlobalVariables.CallPolice = (int)GlobalVariables.CallPoliceStatus.运动控制卡断开连接;
                }
                return false;
            }
        }

        /// <summary>
        /// 验证压力位移是否超了，超了给提示
        /// </summary>
        /// <returns></returns>
        private static bool IsCheck(double num, short AxisNum)
        {
            double MaxPre = 200;
            double MinPre = 20;
            double MaxYa = 20;

            if (num > 0)//向下运动判断最大压力和最大位移
            {
                if (GlobalVariables.Card_Displacement1 >= GlobalVariables.MaximumDisplacement || GlobalVariables.Card_Pressure1 > GlobalVariables.GreatestPressure)
                {
                    CallPolice = (int)CallPoliceStatus.位移达到限位;
                    Helpers.Logger.Instance.Warning($"IsCheck 位移或压力已达到设定的上限");
                    return false;
                }

            }
            else//向下运动判断最小位移
            {
                if (GlobalVariables.Card_Displacement1 <= GlobalVariables.MinimumDisplacement)
                {
                    CallPolice = (int)CallPoliceStatus.位移达到限位;
                    Helpers.Logger.Instance.Warning($"IsCheck 位移已达到设定的最小位移");
                    GlobalVariables.CallPolice = (int)CallPoliceStatus.位移达到限位;
                    return false;
                }
            }

			Helpers.Logger.Instance.Warning($"IsCheck Nothing");
			return true;
        }
    }
}
